package com.jdjc.gateway.redis;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * redis的config处理
 * 与Redis进行数据交换的模板类。
 * 替换jdk序列化方式，避免乱码
 */
@Configuration  // 这个注解表明这个类是一个配置类，Spring会扫描这个类中的Bean定义。
public class RedisConfig {

    @Bean  // 这个注解表明这个方法会返回一个Spring管理的Bean，Bean的名称默认是方法名。
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        // RedisTemplate是一个核心类，用于执行高级的Redis操作（如：存取对象等）。
        RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
        // 创建一个字符串序列化器，用于序列化键。
        RedisSerializer<String> stringSerializer = new StringRedisSerializer();
        // 设置Redis连接工厂，这个工厂是RedisTemplate与Redis服务器通信的桥梁。
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        // 设置键的序列化器。
        redisTemplate.setKeySerializer(stringSerializer);
        // 设置哈希键的序列化器。
        redisTemplate.setHashKeySerializer(stringSerializer);
        // 设置值的序列化器，使用自定义的Jackson2JsonRedisSerializer。
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer());
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer());

        return redisTemplate;
    }

    // 创建一个自定义的Jackson2JsonRedisSerializer，用于序列化值。
    private Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer() {
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        // 设置所有属性的可见性，使得所有属性都可以被序列化。
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // 设置在反序列化时，忽略未知属性，以避免出现异常。
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        // 开启默认类型，以支持不同类型的序列化和反序列化。
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
        // 设置自定义的ObjectMapper。
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
        return jackson2JsonRedisSerializer;
    }
}
